/**
 * 
 */
package blms.system.league;

import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

import blms.system.exception.LeagueDoesNotExistException;
import blms.system.exception.UnknownAttribute;
import blms.system.exception.UserDoesNotExistException;
import blms.system.exception.restrictions.RestrictionException;
import blms.system.user.User;
import blms.system.user.UserEntry;
import blms.system.util.BLMSMessages;
import blms.system.util.ReflectionHelper;
import blms.system.util.Validator;

/**
 * @author thiago
 *
 */
public class LeagueEntry {

	private static int countLeague = 1;
	private final UserEntry userEntry;
	private Map<String, League> leagues = new HashMap<String, League>();
	
	/**
	 * @param userEntry
	 */
	public LeagueEntry(UserEntry userEntry) {
		this.userEntry = userEntry;
	}

	/**
	 * @return
	 */
	public Collection<League> getLeagues() {
		return leagues.values();
	}

	/**
	 * @param leagueName
	 * @return
	 */
	public boolean containsLeague(String leagueName) {
		
		for (League league : leagues.values()) {
			if (league.getName().equals(leagueName)) {
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * @param leagueName
	 * @return
	 */
	public boolean containsLeagueByID(String leagueID) {
		return leagues.containsKey(leagueID);
	}
	
	/**
	 * @param leagueID
	 * @return
	 * @throws LeagueDoesNotExistException
	 */
	public League getLeague(String leagueID) throws LeagueDoesNotExistException {
		
		League league;
		
		if ( (league = leagues.get(leagueID)) == null ) throw new LeagueDoesNotExistException(BLMSMessages.UNKNOWN_LEAGUE_MESSAGE);
		
		return league;
	}
	
	/**
	 * @param name
	 * @return
	 * @throws LeagueDoesNotExistException
	 */
	public List<String> findLeague(String name) throws LeagueDoesNotExistException {
		
		List<String> returnValue = new LinkedList<String>();
		
		for (League league : this.leagues.values()) {
		
			java.util.regex.Pattern p = java.util.regex.Pattern.compile(name, java.util.regex.Pattern.CASE_INSENSITIVE);
			Matcher m = p.matcher(league.getName());
			if (m.matches()) {
				returnValue.add(league.getName());
			}
		}
		
		if (returnValue.isEmpty()) throw new LeagueDoesNotExistException(BLMSMessages.COULD_NOT_FIND_LEAGUE_MESSAGE+" "+name);

		//refactor
		Collections.sort(returnValue);
		return returnValue;
	}

	/**
	 * @param leagueID
	 */
	public void deleteLeague(String leagueID) {
		this.leagues.remove(leagueID);
	}

	/**
	 * 
	 */
	public void removeAllLeagues() {
		this.leagues.clear();
	}

	/**
	 * @param leagueID
	 * @param attribute
	 * @param value
	 * @throws RestrictionException 
	 * @throws LeagueDoesNotExistException 
	 * @throws UserDoesNotExistException 
	 * @throws UnknownAttribute 
	 */
	public void changueLeagueAttributed(String leagueID, String attribute, String value) throws RestrictionException, 
																						LeagueDoesNotExistException,
																							UnknownAttribute, 
																								UserDoesNotExistException {

		if(Validator.isBlankOrNull(attribute)) throw new RestrictionException(BLMSMessages.MUST_PROVIDE_ATTRIBUTE_MESSAGE);
		
		League league = getLeague(leagueID);

		try {
			new ReflectionHelper().getAttribute(league, attribute);
		} catch (UnknownAttribute e) {
			throw new RestrictionException(BLMSMessages.UNKNOWN_LEAGUE_ATTRIBUTE_MESSAGE);
		}
		
		{//operator att validation
			if ("operator".equals(attribute)) {
				
				if (Validator.isBlankOrNull(value)) {
					throw new RestrictionException(BLMSMessages.REQUIRED_DATA_MESSAGE + "league operator");
				}
				
				if (!userEntry.containsUser(value)) {
					throw new RestrictionException(BLMSMessages.UNKNOWN_USER_MESSAGE);
				}
			}
		}

		{//league name att
			if (containsLeague(value)) {
				throw new RestrictionException(BLMSMessages.LEAGUE_ALREADY_EXISTS_MESSAGE);
			}
			
			if (Validator.isBlankOrNull(value)) {
				throw new RestrictionException(BLMSMessages.REQUIRED_DATA_MESSAGE + "league name");
			}
		}
		
		//refactor
		if (attribute.equals("operator")) {
			new ReflectionHelper().setAttribute(league, attribute, userEntry.getUser(value));
		}else new ReflectionHelper().setAttribute(league, attribute, value);

	}

	public String getLeagueAttribute(String id, String attribute) throws LeagueDoesNotExistException, UnknownAttribute {
		
		try {
			return new ReflectionHelper().getAttribute(getLeague(id), attribute);
		} catch (UnknownAttribute e) {
			throw new UnknownAttribute(BLMSMessages.UNKNOWN_LEAGUE_ATTRIBUTE_MESSAGE);
		}
	}

	private String generateNewID() {
		return ++countLeague+"";
	}
	
	/**
	 * @param name
	 * @param userOperator
	 * @param creationDate
	 * @return
	 * @throws RestrictionException
	 */
	public League createLeague(String name, User userOperator, Date creationDate) throws RestrictionException {
		
		if (containsLeague(name)) throw new RestrictionException(BLMSMessages.LEAGUE_ALREADY_EXISTS_MESSAGE);
		League league = new League(generateNewID(), name, userOperator, creationDate);
		leagues.put(league.getId(), league);
		
		return league;
	}
}